// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FIXApplication.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.Forge.Plugins
{
    #region Using Directives

    using System;
    using System.Security.Cryptography;
    using System.Text;

    using QuickFix;

    #endregion

    /// <summary>
    /// The fix application.
    /// </summary>
    public abstract class FIXApplication : MessageCracker, QuickFix.Application
    {
        #region Properties

        /// <summary>
        /// Gets or sets the logon event cb.
        /// </summary>
        public EventHandler<SessionIDEventArgs> LogonEventCB { get; set; }

        /// <summary>
        /// Gets or sets the logout event cb.
        /// </summary>
        public EventHandler<SessionIDEventArgs> LogoutEventCB { get; set; }

        #endregion

        #region Implemented Interfaces

        #region Application

        /// <summary>
        /// The from admin.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="sessionId">
        /// The sessionId.
        /// </param>
        public void fromAdmin(Message message, SessionID sessionId)
        {
            Stdout.WriteLine(message);
        }

        /// <summary>
        /// The from app.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="sessionId">
        /// The sessionId.
        /// </param>
        public void fromApp(Message message, SessionID sessionId)
        {
            try
            {
                Stdout.WriteLine(message);
                this.crack(message, sessionId);
            }
            catch (Exception e)
            {
                Stdout.WriteLine("fromApp: Exception: " + e + " Session: " + sessionId + " message: " + message);
            }
        }

        /// <summary>
        /// The on create.
        /// </summary>
        /// <param name="sessionId">
        /// The sessionId.
        /// </param>
        public void onCreate(SessionID sessionId)
        {
        }

        /// <summary>
        /// The on logon.
        /// </summary>
        /// <param name="sessionId">
        /// The sessionId.
        /// </param>
        public void onLogon(SessionID sessionId)
        {
            if (this.LogonEventCB != null)
            {
                this.LogonEventCB(this, new SessionIDEventArgs(sessionId));
            }

            // Stdout.WriteLine("onLogon: Session " + sessionId);
        }

        /// <summary>
        /// The on logout.
        /// </summary>
        /// <param name="sessionId">
        /// The sessionId.
        /// </param>
        public void onLogout(SessionID sessionId)
        {
            if (this.LogoutEventCB != null)
            {
                this.LogoutEventCB(this, new SessionIDEventArgs(sessionId));
            }

            // Stdout.WriteLine("onLogout: Session " + sessionId);
        }

        /// <summary>
        /// The to admin.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="sessionId">
        /// The sessionId.
        /// </param>
        public void toAdmin(Message message, SessionID sessionId)
        {
            var mbtWorkaround = true;

            // MBT Workaround
            if (mbtWorkaround)
            {
                if (message is QuickFix44.Logon)
                {
                    var cleartext = "1book2mice";

                    // Hash password
                    var sha256 = new SHA256Managed();
                    var cleartextAsciiByteArray = ASCIIEncoding.ASCII.GetBytes(cleartext);
                    var sha256HexstringPassword = BitConverter.ToString(sha256.ComputeHash(cleartextAsciiByteArray));
                    sha256HexstringPassword = sha256HexstringPassword.Replace("-", string.Empty);

                    // MBT AddField: Password(554)
                    message.setField(new Password(sha256HexstringPassword));

                    // MBT AddField: FieldHashed(347) [FieldName 554 is hashed using H1 (SHA256)]
                    message.setField(new StringField(347, "554H1"));
                }
            }

            Stdout.WriteLine(message);
        }

        /// <summary>
        /// The to app.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <param name="sessionId">
        /// The sessionId.
        /// </param>
        public void toApp(Message message, SessionID sessionId)
        {
            Stdout.WriteLine(message);
        }

        #endregion

        #endregion
    }
}